//User Interface Class
window.UserInterface = function(){
	//Set a variable reference to 'this' instance of the class.
	//The reserve word this can be used to refer to different things inside the class.
	//Assigning a variable makes it easier to follow the code.  
	//Could be anything.
	var base = this;
	
	/*PUBLIC FUNCTION
	 * PARAM: none;
	 * RETURN: none;
	 * This function simulates a constructor function
	 * We call it inside the object(Last line of UserInterface), but could be called externally.
	 * The main purpose of this function is to assign the event listeners
	 */
	base.initialize = function(){
		//Assign tab links to a public collection
		base.tabs = document.getElementById('tabList').getElementsByTagName('a');
		
		//Add Event Listeners
		if(window.addEventListener){//Netscape based browsers
			//loop through tabs adding listeners
			for(var i = 0; i < base.tabs.length; i++)
				base.tabs[i].addEventListener('click', function(e){var elem = eHandler(e); base.tabEvent(elem); return false;}, true);
		}
		else if(window.attachEvent){//IE based browsers
			//loop through tabs adding listeners
			for(var i = 0; i < base.tabs.length; i++)
				base.tabs[i].attachEvent('onclick', function(){var elem = eHandler(null); base.tabEvent(elem); return false;});
		}
		else{//Backward compatibility for older browsers
			//loop through tabs adding listeners
			for(var i = 0; i < base.tabs.length; i++)
				base.tabs[i].onclick = function(){var elem = eHandler(null); base.tabEvent(elem); return false;};
		}
		
		
	};
	
	/* PRIVATE FUNCTION
	 * PARAM: e is the event object passed in by Netscape browsers
	 * RETURN: elem is the element that triggered the event
	 * This generic event handler function is handling cross browser issues.
	 * It could be used for multiple types of events where doing something
	 * with the triggered element is the main goal 
	 */
	var eHandler = function(e){
		var event = (e)? e : window.event;
		var elem = (event.target)? event.target : event.srcElement;
		if(event.cancelable)
			event.preventDefault();
		return elem;
	};
	
	/*PUBLIC FUNCTION 
	 * PARAM: elem is the tab link that was clicked
	 * RETURN: none;
	 * This event handler function controls the look and feel of
	 * the tab interface.  Then calls getContent to fill the page
	 */
	base.tabEvent = function(elem){
		//Loop through all tabs
		for(var i = 0; i < base.tabs.length; i++){
			//Use the tab link's href attribute to get the id of tab's content area
			var id = base.tabs[i].href.split('#')[1]; 
			
			//If this tab was the one clicked make it active
			if(base.tabs[i].href == elem.href){
				//Show content area
				document.getElementById(id).style.display = 'block';
				//Make the active tab look different
				base.tabs[i].parentNode.className = 'active-tab';
				//get the content for the active tab
				getContent(id);
			}
			else{
				//Hide inactive tab content areas
				document.getElementById(id).style.display = 'none';
				//Make inactive tabs look inactive
				base.tabs[i].parentNode.className = 'inactive-tab';
			}
		}
	};
	
	/*PRIVATE FUNCTION
	 * PARAM: id is the id for the container which will hold the content.
	 * RETURN: none;
	 * This function would not normally be needed.  We are using it as a way
	 * to branch into three different ways to use AJAX.  A normal project
	 * would not use three ways to get the same thing.
	 */
	var getContent = function(id){
		//Get the element that content will be added to
		var container = document.getElementById(id);
		switch(id){
		case 'tab1':
			//get html content and simply assign to the tab
			makeAJAXRequest('get','440.html',container, passThroughHTML);
			break;
		case 'tab2':
			//Get json content and transform to html
			makeAJAXRequest('get','440.txt',container, transformJSON);
			break;
		case 'tab3':
			//Get xml content and transform to html
			makeAJAXRequest('get','440.xml',container, transformXML);
			break;
		}
	};
	
	/*PRIVATE FUNCTION
	 * PARAM: method of request get, post, or head
	 * PARAM: url location of the data being requested
	 * PARAM: container is the location in the html page that the returned data is to be placed
	 * PARAM: callback is a function that gets called when a response is returned from the server
	 * RETURN:  The html to be displayed
	 * This function handles the ajax call itself.  
	 */
	var makeAJAXRequest = function(method,url,container, callback){
		//Create a cross browser request object
		var xmlHttp = createXMLHttpRequest();
		
		//Test that a valid request object was created
		if (!xmlHttp) {
			container.innerHTML = "ERROR:  Your browser doesn't support AJAX."
			return;//Break out if error
		}
			
		//Assign an event handler function to the onreadystate event listener
		xmlHttp.onreadystatechange = function() {
			//request is complete and request was successful
			if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
				//xml document retrieved
				if(url.split('.')[1] == 'xml')
					//Assign transformed data to the html page
					container.innerHTML = callback(xmlHttp.responseXML);
				//all other documents
				else
					//Assign transformed data to the html page
					container.innerHTML = callback(xmlHttp.responseText);
			}
		}
				
		// Open then send a request
		xmlHttp.open(method, url, true);
		xmlHttp.send(null);
	};
	
	/*PRIVATE FUNCTION
	 * PARAM: none;
	 * RETURN: CROSS BROWSER REQUEST OBJECT OR null if browser doesn't support AJAX
	 * This function handles the cross browser issues involved in making an AJAX request
	 */
	var createXMLHttpRequest = function(){
		//Set the return variable to null
		var xmlHttp = null;
		
		//If Netscape based Browser
		if (window.XMLHttpRequest) 		
			xmlHttp = new XMLHttpRequest();
		//If IE based browser
		else if (window.ActiveXObject) {
			//Versions of this Active X Object from newest to oldest
			var versions = ["MSXML2.XMLHttp.5.0",
							"MSXML2.XMLHttp.4.0",
							"MSXML2.XMLHttp.3.0",
							"MSXML2.XMLHttp",
							"Microsoft.XMLHttp"];
				
			//Loop through versions
			for (var i=0; i<versions.length; i++) {
				try {
					//Attempt to create the request object
					xmlHttp = new ActiveXObject(versions[i]);
							
					// Object was successfully created stop the loop
					break;
				} catch(e) {
					// Request failed to be created allow loop to try again
				}		
			}
		}
		//Return request object or null	
		return xmlHttp;
	};
	
	/*PRIVATE FUNCTION
	 * PARAM: responseText from AJAX request
	 * RETURN: responseText unchanged;
	 * This function simply passes through the html returned from the server without transformation
	 */
	var passThroughHTML = function(html){
		return html;
	};
	
	/*PRIVATE FUNCTION
	 * PARAM: responseText from AJAX Request as JSON
	 * RETURN: responseText transformed from JSON to html
	 * This function parses a responseText string into javascript then
	 * transforms the resulting JSON object to html
	 */
	var transformJSON = function(txt){
		//Parse the document text into Javascript
		eval(txt);
		
		//Create html string
		var html = '<table id="table" border="0">';
		html += '<caption>';
		html += '<h3>' + data.courseTitle + '</h3>';
		html += '<p align="left">' + data.courseDescription + '</p>';
		html += '</caption>';
		html += '<thead>';
		html += '<tr><th>NUID</th><th>First Name</th><th>Last Name</th><th>Class Standing</th></tr>';
		html += '</thead>';
		html += '<tbody>';
		
/*		for(var i=0; i<students.length; i++){
			html += '<tr>';
			html += '<td>' + students[i].getAttribute('nuid') + '</td>';
			var record = students[i].firstChild;
			do{
				if(record.nodeName != '#text')
					html += '<td>'+ record.firstChild +'</td>';
				
				record = record.nextSibling;
			}
		}*/
		
		//Loop through student elements
		for(var i = 0; i < data.students.length; i++){
			html += '<tr>';
			//Loop through student object
			for(field in data.students[i])
				html += '<td>' + data.students[i][field] + '</td>';
			html += '</tr>';
		}
		html += '</tbody>';
		html += '</table>';
		return html;
	};
	
	/*PRIVATE FUNCTION
	 * PARAM: xml document from AJAX Request
	 * RETURN: html string representing data
	 * This function uses the xml nodetree to create an html representation of the data. 
	 */
	var transformXML = function(xml){
		//Get the course title from the root element tag
		var title = xml.firstChild.nodeName;
		if(title == 'xml')//IE returns xml declaration as the first node so need to dig deeper
			title = xml.firstChild.nextSibling.nodeName;
		//Get couse Description
		var description = xml.getElementsByTagName('description')[0].firstChild.nodeValue;
		//Get array of student elements
		var students = xml.getElementsByTagName('student');
		//create html string
		var html = '<table id="table" border="0">';
		html += '<caption>';
		html += '<h3>' + title + '</h3>';
		html += '<p align="left">' + description + '</p>';
		html += '</caption>';
		html += '<tr><th>NUID</th><th>First Name</th><th>Last Name</th><th>Class Standing</th></tr>';
		html += '</thead>';
		html += '<tbody>';
		//Loop through student elements
		for(var i = 0; i < students.length; i++){
			html += '<tr>';
			
			//NUID is stored as an attribute not an element			
			var nuid = students[i].getAttribute('nuid');			
			html += '<td>' + nuid + '</td>';
			
			//get first node in current student
			var record = students[i].firstChild;
			//Loop through child elements of student[i] using nextSibling.
			do{
				//Cross browser check to filter out empty text nodes before adding them to the html
				if(record.nodeName != '#text')
					html += '<td>' + record.firstChild.nodeValue + '</td>';
				
				//iterate to next child
				record = record.nextSibling;
			}
			while(record);//record will evaluate to false if nextSibling didn't return a valid node
			html += '</tr>';
		}
		html += '</tbody>';
		html += '</table>';
		return html;
	};
	
	//Call the constructor.  This could also be done outside the class	
	base.initialize();
};

